home *** CD-ROM | disk | FTP | other *** search
/ HyperLib 1997 Winter - Disc 1 / HYPERLIB-1997-Winter-CD1.ISO.7z / HYPERLIB-1997-Winter-CD1.ISO / 第1特集Plug-in / Photoshop / Dan's Pascal Plug-In.sit / Dan's Pascal Plug-In / Dan's Acquisition Plug-In < prev    next >
Text File  |  1994-04-26  |  23KB  |  799 lines

  1. (************************************************************************)
  2. (*    an example programme for a Photoshop acquisition plug-in     *)
  3. (*              by Daniel W. Rickey                *)
  4. (*            London, Ontario, CANADA                *)
  5. (*            drickey@irus.rri.uwo.ca                *)
  6. (*            written in Think Pascal                *)
  7. (*        based on an MPW example programme by Thomas Knoll    *)
  8. (*            last modified 1994-04-27            *)
  9. (*                                    *)
  10. (*    Note that this Plug-in assumes that System 7.0 or newer is used    *)
  11. (************************************************************************)
  12. Unit ExampleAcquisition;
  13.  
  14. Interface
  15.  
  16.     Uses
  17.         AcquireInterface;
  18.  
  19.   {When a plug-in module is called, Adobe Photoshop opens the resource fork}
  20.   {of the plug-in file, loads the resource into to memory and locks it.}
  21.   {The plug-in is then called starting at the first byte of the resource with the}
  22.   {following calling convention:}
  23.     Procedure Main (selector: Integer; AcquireRecord: AcquireRecordPtr; Var myData: Handle; Var result: Integer);
  24.  
  25. Implementation
  26.  
  27.     Const
  28.         kAbortAcquisition = 1;    {an error occurred or the user selected cancel}
  29.  
  30.     (* the following are key codes to be used in dialogue box filters *)
  31.         kEnterKey = $03;
  32.         kBackSpace = $08;
  33.         kTabKey = $09;
  34.         kReturnKey = $0D;
  35.         kEscKey = $1B;
  36.         kLeftArrow = $1C;
  37.         kRightArrow = $1D;
  38.         kUpArrow = $1E;
  39.         kDownArrow = $1F;
  40.         kDeleteKey = $7F;
  41.  
  42.     (* these are friendly keys and are passed through the filters *)
  43.         kControlKeys = [kBackSpace, kTabKey, kLeftArrow, kRightArrow, kUpArrow, kDownArrow, kDeleteKey];
  44.  
  45.     Type
  46.     {keep all of our variables in one record handle}
  47.     {this will be used instead of keeping global variables}
  48.         myDataType = Record
  49.                 Acquire: AcquireRecordPtr;
  50.                 Result: Integer;
  51.  
  52.                 LastRows: Integer;    {keep track of the image size and type}
  53.                 LastCols: Integer;    {If the plug-in is called more than once, the last}
  54.                 LastMode: Integer;    {set of parameters will be presented to the user.}
  55.  
  56.                 ImageRow: Integer;    {Image row being acquired; 1..Number of rows}
  57.                 ImagePlane: Integer;    {image plane being acquired; 0..3}
  58.             End;
  59.  
  60.         myDataPtr = ^myDataType;
  61.         myDataHand = ^myDataPtr;
  62.  
  63.  
  64.   (**** Calls the host's TestAbort function ****)
  65.   (**** may call this several times a second to allow the user to abort the acquisition ****)
  66.   (**** this also changes the cursor to a watch and periodically moves the watch hands ****)
  67.     Function TestAbort (myData: myDataHand): Boolean;
  68.         Var
  69.             address: ProcPtr;
  70.  
  71.         Function DoTestAbort (codeAddress: ProcPtr): Boolean;
  72.         Inline
  73.             $205F, $4E90;
  74.  
  75.     Begin
  76.     TestAbort := FALSE;
  77.     Exit(TestAbort);
  78.  
  79.     address := myData^^.Acquire^.abortProc;
  80.     TestAbort := DoTestAbort(address);
  81.     End;  {TestAbort}
  82.  
  83.  
  84.   (**** Calls the host's UpdateProgress procedure ****)
  85.   (**** The first parameter is the number of operations completed ****)
  86.   (**** the second is the total number of operations to do ****)
  87.     Procedure UpdateProgress (NumberDone, total: LongInt; myData: myDataHand);
  88.         Var
  89.             address: ProcPtr;
  90.  
  91.         Procedure DoUpdateProgress (NumberDone, total: LongInt; CodeAddress: ProcPtr);
  92.         Inline
  93.             $205F, $4E90;
  94.  
  95.     Begin
  96.     address := myData^^.Acquire^.ProgressProc;
  97.     DoUpdateProgress(NumberDone, total, address);
  98.     End;  {UpdateProgress}
  99.  
  100.  
  101.   (**** Displays the about dialogue box for the plug-in module. ****)
  102.     Procedure DoAbout;
  103.         Const
  104.             kDialogueID = 16000;
  105.  
  106.         Var
  107.             theDialogueHand: DialogTHndl;
  108.             theDialogue: DialogPtr;
  109.             theItem: Integer;
  110.  
  111.  
  112.     Begin
  113.   {load the dialgue resource into memory and lock it}
  114.     theDialogueHand := DialogTHndl(GetResource('DLOG', kDialogueID));
  115.     HNoPurge(Handle(theDialogueHand));
  116.  
  117.   {get our about dialogue from the resource}
  118.     theDialogue := GetNewDialog(kDialogueID, Nil, WindowPtr(-1));
  119.  
  120.   {display the dialogue and wait for the user to select okay}
  121.     ModalDialog(Nil, theItem);
  122.  
  123.   {get rid of the dialogue window and the resource}
  124.     DisposDialog(theDialogue);
  125.     HPurge(Handle(theDialogueHand))
  126.     End;  {DoAbout}
  127.  
  128.  
  129.   (**** Prepare to acquire an image.  If the plug-in module needs only a limited ****)
  130.   (****  amount of memory, it can lower the value of the 'maxData' field. ****)
  131.     Procedure DoPrepare (myData: myDataHand);
  132.     Begin
  133.   {Photoshop initialises maxData to the maximum of number of bytes it can free}
  134.   {divide by two to give half to photoshop and half to the plug-in}
  135.     myData^^.Acquire^.maxData := myData^^.Acquire^.maxData Div 2;
  136.     End;  {DoPrepare}
  137.  
  138.  
  139.   (**** outlines the OK button in a dialogue box ****)
  140.   (**** this is from the new inside mac, Toolbox essentials ****)
  141.     Procedure OutlineOKbutton (theDialogue: DialogPtr; TheItem: Integer);
  142.         Const
  143.             kOkayButton = 1;
  144.             kButtonFrameInset = -4;
  145.             kButtonFrameSize = 3;
  146.  
  147.         Var
  148.             itemType: Integer;
  149.             itemRect: Rect;
  150.             ItemHandle: Handle;
  151.             CurrentPen: PenState;
  152.             ButtonOval: Integer;
  153.             OldPort: WindowPtr;
  154.             thePattern: Pattern;
  155.  
  156.     Begin
  157.     GetDItem(theDialogue, kOkayButton, itemType, ItemHandle, itemRect);
  158.  
  159.     GetPort(OldPort);
  160.     SetPort(ControlHandle(itemHandle)^^.ContrlOwner);
  161.  
  162.     GetPenState(CurrentPen);
  163.     PenNormal;
  164.     InsetRect(itemRect, kButtonFrameInset, kButtonFrameInset);
  165.     FrameRoundRect(itemRect, 16, 16);
  166.     ButtonOval := (ItemRect.Bottom - ItemRect.Top) Div 2 + 2;
  167.  
  168.   {get the black pen pattern from the system resource}
  169.     GetIndPattern(thePattern, 0, 1);
  170.   {set the pen pattern to black; can not use "Black" since it is an A5 QD global}
  171.     PenPat(thePattern);
  172.  
  173.     PenSize(kButtonFrameSize, kButtonFrameSize);
  174.     FrameRoundRect(itemRect, ButtonOval, ButtonOval);
  175.  
  176.     SetPenState(CurrentPen);
  177.     SetPort(OldPort);
  178.     End;  {OutlineOKbutton}
  179.  
  180.  
  181.   (**** filter key strokes function for the image parameters dialogue window ****)
  182.   (**** allows only numbers to be entered in the image width and height text boxes ****)
  183.     Function myImageParametersFilter (theDialogue: DialogPtr; Var TheEvent: EventRecord; Var ItemHit: Integer): Boolean;
  184.         Const
  185.             kDialogueID = 16001;
  186.             kOkayItem = 1;
  187.             kCancelItem = 2;
  188.             kImageWidthItem = 3;
  189.             kImageHeightItem = 4;
  190.  
  191.             kBitMapItem = 5;
  192.             kGreyScaleItem = 6;
  193.             kColourItem = 7;
  194.             kRGBcolourItem = 8;
  195.  
  196.             kOkayOutlineItem = 13;
  197.  
  198.             DefaultItem = kOkayItem;
  199.  
  200.         Var
  201.             Key: Integer;
  202.             TextField: Integer;
  203.  
  204.     Begin
  205.     myImageParametersFilter := FALSE;
  206.  
  207.   (* check if a key was pressed, or an autoRepeat happened *)
  208.     If (TheEvent.What = KeyDown) Or (TheEvent.What = AutoKey) Then
  209.         Begin
  210.     (* check what text field the keystokes are occuring in *)
  211.         TextField := DialogPeek(TheDialogue)^.EditField + 1;
  212.  
  213.     {get the key that was pressed}
  214.         Key := band(TheEvent.Message, CharCodeMask);
  215.  
  216.     {if the key was a control key, or in the range 0 to 9, then do not filter it}
  217.         If (Key In kControlKeys) Or (Key In [Ord('0')..Ord('9')]) Then
  218.             Begin
  219.             myImageParametersFilter := FALSE;
  220.             End
  221.     {if the enter or return key was pressed, then pass back okay button selected}
  222.         Else If Key In [kEnterKey, kReturnKey] Then
  223.             Begin
  224.             myImageParametersFilter := TRUE;
  225.             ItemHit := DefaultItem;
  226.             End
  227.     {if we are in a text field and a non-numeric key is pressed then filter}
  228.         Else If (TextField In [kImageWidthItem, kImageHeightItem]) And Not (Key In [Ord('0')..Ord('9')]) Then
  229.             Begin
  230.             myImageParametersFilter := TRUE;
  231.             End;
  232.  
  233.         End;  {If KeyDown}
  234.     End;    {myImageParametersFilter}
  235.  
  236.  
  237.   (**** Converts a string to a number between 1 and 30000 ****)
  238.   (****  Returns false if not a valid number or out of range ****)
  239.     Function ConvertString (theString: Str255; Var theNumber: Integer): Boolean;
  240.  
  241.         Var
  242.             Loop: Integer;
  243.             x: LongInt;
  244.  
  245.     Begin
  246.     ConvertString := FALSE;
  247.  
  248.   {loop through all of the characters in the string and make sure all are numbers}
  249.   {we do not really need to do this as the dialogue filter should have filtered}
  250.   {all non-numeric characters}
  251.     For Loop := 1 To Length(theString) Do
  252.         Begin
  253.         If Not (theString[Loop] In ['0'..'9']) Then
  254.             Begin
  255.             EXIT(ConvertString);
  256.             End;
  257.         End;
  258.  
  259.   {convert the string to a long integer}
  260.     StringToNum(theString, x);
  261.  
  262.   {make sure the number is reasonable }
  263.     If (x > 0) And (x < 30001) Then
  264.         Begin
  265.         ConvertString := TRUE;
  266.         theNumber := x;
  267.         End;
  268.  
  269.     End;  {ConvertString}
  270.  
  271.  
  272.   (**** Prompt the user for the image parameters; Returns false if the user cancels ****)
  273.     Function GetImageParameters (Var ImageWidth, ImageHeight, mode: Integer): BOOLEAN;
  274.         Const
  275.             kDialogueID = 16001;
  276.             kOkayItem = 1;
  277.             kCancelItem = 2;
  278.             kImageWidthItem = 3;
  279.             kImageHeightItem = 4;
  280.  
  281.             kBitMapItem = 5;
  282.             kGreyScaleItem = 6;
  283.             kColourItem = 7;
  284.             kRGBcolourItem = 8;
  285.  
  286.             kOkayOutlineItem = 13;
  287.  
  288.         Var
  289.             itemRect: Rect;
  290.             WidthString, HeightString: Str255;
  291.             ItemHandle: Handle;
  292.             TheDialogue: DialogPtr;
  293.             TheDialogueHand: DialogTHndl;
  294.             TheItem: Integer;
  295.  
  296.             itemType: Integer;
  297.  
  298.             WidthText: Handle;
  299.             HeightText: Handle;
  300.             bButton: ControlHandle;
  301.             gButton: ControlHandle;
  302.             iButton: ControlHandle;
  303.             cButton: ControlHandle;
  304.  
  305.             Done: Boolean;
  306.  
  307.     Begin
  308.     Done := FALSE;
  309.   {load our dialogue resource into memory to make sure we do not}
  310.   {use another plug-in's dialogue}
  311.     TheDialogueHand := DialogTHndl(GetResource('DLOG', kDialogueID));
  312.     HNoPurge(Handle(TheDialogueHand));
  313.  
  314.   {get our dialogue from the dialogue resource}
  315.     TheDialogue := GetNewDialog(kDialogueID, Nil, WindowPtr(-1));
  316.  
  317.   {get a handle to the "user" button outline item}
  318.     GetDItem(TheDialogue, kOkayOutlineItem, itemType, ItemHandle, itemRect);
  319.  
  320.   {install the drawing routine for the application defined button outline}
  321.     SetDItem(TheDialogue, kOkayOutlineItem, itemType, Handle(@OutlineOKbutton), itemRect);
  322.  
  323.   {set the image height value in the text edit box}
  324.     GetDItem(TheDialogue, kImageHeightItem, itemType, HeightText, itemRect);
  325.     NumToString(ImageHeight, HeightString);
  326.     SetIText(HeightText, HeightString);
  327.  
  328.   {set the image width value in the text edit box}
  329.     GetDItem(TheDialogue, kImageWidthItem, itemType, WidthText, itemRect);
  330.     NumToString(ImageWidth, WidthString);
  331.     SetIText(WidthText, WidthString);
  332.  
  333.   {select all of the text in the Image width text edit box}
  334.     SelIText(TheDialogue, kImageWidthItem, 0, 32767);
  335.  
  336.     Repeat
  337.     {set the states of the four image mode radio-buttons}
  338.         GetDItem(TheDialogue, kBitMapItem, itemType, Handle(bButton), itemRect);
  339.         SetCtlValue(bButton, ORD(mode = acquireModeBitmap));
  340.  
  341.         GetDItem(TheDialogue, kGreyScaleItem, itemType, Handle(gButton), itemRect);
  342.         SetCtlValue(gButton, ORD(mode = acquireModeGrayScale));
  343.  
  344.         GetDItem(TheDialogue, kColourItem, itemType, Handle(iButton), itemRect);
  345.         SetCtlValue(iButton, ORD(mode = acquireModeIndexedColor));
  346.  
  347.         GetDItem(TheDialogue, kRGBcolourItem, itemType, Handle(cButton), itemRect);
  348.         SetCtlValue(cButton, ORD(mode = acquireModeRGBColor));
  349.  
  350.     {wait for the user to select something}
  351.         ModalDialog(@myImageParametersFilter, theItem);
  352.  
  353.         Case theItem Of
  354.         kBitMapItem: 
  355.             Begin
  356.             mode := acquireModeBitmap;
  357.             End;
  358.         kGreyScaleItem: 
  359.             Begin
  360.             mode := acquireModeGrayScale;
  361.             End;
  362.         kColourItem: 
  363.             Begin
  364.             mode := acquireModeIndexedColor;
  365.             End;
  366.         kRGBcolourItem: 
  367.             Begin
  368.             mode := acquireModeRGBColor;
  369.             End;
  370.  
  371.         kOkayItem: {user selected okay button or pressed the return key}
  372.             Begin
  373.       {get both the image width and image height strings from the text edit boxes}
  374.             GetIText(WidthText, WidthString);
  375.             GetIText(HeightText, HeightString);
  376.  
  377.       {convert the width and height strings to numbers}
  378.       {if an error then beep & select the offending text}
  379.             If Not ConvertString(WidthString, ImageWidth) Then
  380.                 Begin
  381.                 SelIText(TheDialogue, kImageWidthItem, 0, 32767);
  382.                 SysBeep(1);
  383.                 End
  384.             Else If Not ConvertString(HeightString, ImageHeight) Then
  385.                 Begin
  386.                 SelIText(TheDialogue, kImageHeightItem, 0, 32767);
  387.                 SysBeep(1);
  388.                 End
  389.             Else
  390.                 Begin
  391.         {if there were no errors, then return true and exit the loop}
  392.                 GetImageParameters := TRUE;
  393.                 Done := TRUE;
  394.                 End;
  395.             End;
  396.  
  397.         kCancelItem: 
  398.             Begin
  399.       {user selected cancel, so exit and return a false value}
  400.             GetImageParameters := FALSE;
  401.             Done := TRUE;
  402.             End;
  403.  
  404.         Otherwise
  405.             Begin
  406.             End;
  407.         End;  {Case theItem}
  408.  
  409.     Until Done;
  410.  
  411.   {get rid of our dialogue window}
  412.     DisposDialog(TheDialogue);
  413.  
  414.   {remove our dialogue resource from memory}
  415.     HPurge(Handle(TheDialogueHand));
  416.     End;  {GetImageParameters}
  417.  
  418.  
  419. (**** Asks the user and the returns the image parmaters to the calling program ****)
  420. (**** This call lets Photoshop know the mode, size and resolution of the image ****)
  421. (**** being returned, so Photoshop can allocate and initialise its data structures ****)
  422. (* The plug-in will display the dialogue box during this call and set the ****)
  423. (**** imageMode, imageSize,depth, planes, imageHRes and imageVRes fields. ****)
  424. (**** For an indexed color image, the redLUT , greenLUT and blueLUT fields are set ****)
  425. (**** If a duotone mode image is being acquired, the duotoneInfo field is set ****)
  426.     Procedure DoStart (myData: myDataHand);
  427.         Var
  428.             j: Integer;
  429.  
  430.     Begin
  431.  
  432.     With myData^^, myData^^.Acquire^ Do
  433.         Begin
  434.  
  435.         imageSize.v := LastRows;
  436.         imageSize.h := LastCols;
  437.         imageMode := LastMode;
  438.  
  439.     (* get the image size and mode from the user; exit if canceled *)
  440.         If Not GetImageParameters(imageSize.v, imageSize.h, imageMode) Then
  441.             Begin
  442.             Result := kAbortAcquisition;
  443.             Exit(DoStart)
  444.             End;
  445.  
  446.     (* keep track of the user's choices for next time this is called *)
  447.         LastRows := imageSize.v;
  448.         LastCols := imageSize.h;
  449.         LastMode := imageMode;
  450.  
  451.     (* start with image plane 0; = red for RGB images *)
  452.         ImagePlane := 0;
  453.  
  454.     (* start with the first row of the image plane *)
  455.         ImageRow := 1;
  456.  
  457.     (* initialise the host's image parameter record with appropriate values *)
  458.         Case ImageMode Of
  459.         acquireModeBitmap: 
  460.             Begin
  461.             Depth := 1;            (* 1 Bit per sample/pixel *)
  462.             Planes := 1;            (* 1 sample per pixel *)
  463.             imageHRes := FixRatio(300, 1);    (* 300 Horizontal Pixels per inch *)
  464.             imageVRes := FixRatio(300, 1);    (* 300 Vertical Pixels per inch *)
  465.             End;
  466.  
  467.         acquireModeGrayScale: 
  468.             Begin
  469.             Depth := 8;            (* 8 Bits per sample/pixel *)
  470.             Planes := 1;            (* 1 sample per pixel *)
  471.             imageHRes := FixRatio(72, 1);    (* 72 Horizontal Pixels per inch *)
  472.             imageVRes := FixRatio(72, 1);    (* 72 Vertical Pixels per inch *)
  473.             End;
  474.  
  475.         acquireModeIndexedColor: 
  476.             Begin
  477.             Depth := 8;
  478.             Planes := 1;
  479.             imageHRes := FixRatio(72, 1);
  480.             imageVRes := FixRatio(72, 1);
  481.  
  482.       {initialise the Look-Up-Tables that are used for indexed colours only}
  483.       {the following is an arbitrary colour LUT}
  484.             For j := 0 To 255 Do
  485.                 Begin
  486.                 redLUT[j] := CHR(j);
  487.                 greenLUT[j] := CHR(255 - j);
  488.                 blueLUT[j] := CHR(j Div 2)
  489.                 End;
  490.             End;
  491.  
  492.         acquireModeRGBColor: 
  493.             Begin
  494.             Depth := 8;
  495.             Planes := 3;
  496.             imageHRes := FixRatio(72, 1);
  497.             imageVRes := FixRatio(72, 1);
  498.             End;
  499.  
  500.         acquireModeCMYKColor: 
  501.             Begin
  502.             End;
  503.  
  504.         acquireModeHSLColor: 
  505.             Begin
  506.             End;
  507.  
  508.         acquireModeHSBColor: 
  509.             Begin
  510.             End;
  511.  
  512.         acquireModeMultichannel: 
  513.             Begin
  514.             End;
  515.  
  516.         acquireModeDuotone: 
  517.             Begin
  518.             End;
  519.  
  520.         Otherwise
  521.             Begin
  522.             Result := kAbortAcquisition;
  523.             End;
  524.         End;  {Case ImageMode}
  525.  
  526.         End;  {With}
  527.     End;  {DoStart}
  528.  
  529.  
  530.   (**** This call returns a strip of the image to Photoshop. ****)
  531.   (**** Photoshop will continue to call this routine until an error is returned ****)
  532.   (**** or the data field is set to Nil.*)
  533.     Procedure DoContinue (myData: myDataHand);
  534.         Var
  535.             TheStripPtr: Ptr;
  536.             aRow: LongInt;
  537.             aColumn: LongInt;
  538.             RowsInStrip: LongInt;
  539.  
  540.     Begin
  541.  
  542.     With myData^^, myData^^.Acquire^ Do
  543.         Begin
  544.  
  545.     {if any data is left from the previous call, dispose of it}
  546.         If data <> Nil Then
  547.             Begin
  548.             DisposPtr(data);
  549.             data := Nil
  550.             End;
  551.  
  552.     (* the plug-in returns the image data in the "data" field of the acquisition record *)
  553.     (* the image can be returned in many strips; maximum strip size is set by "maxData" *)
  554.     (* The area of the image strip being returned is specified by theRect and by the loPlane and hiPlane fields. *)
  555.  
  556.     (* the byte spacing between columns; we will send each image plane separately *)
  557.         colBytes := 1;
  558.  
  559.     (* this is the number of bytes in one image row, i.e., the byte spacing between rows *)
  560.         If depth = 8 Then
  561.             Begin
  562.             rowBytes := imageSize.h
  563.             End
  564.         Else
  565.             Begin
  566.             rowBytes := BSR(imageSize.h + 7, 3);
  567.             End;
  568.  
  569.     (* determine the maximum number of image rows that can fit into a strip *)
  570.         RowsInStrip := maxData Div rowBytes;
  571.  
  572.     {make sure the size of a single row is not larger than the biggest strip buffer}
  573.         If RowsInStrip < 1 Then
  574.             Begin
  575.             Result := memFullErr;
  576.             EXIT(DoContinue)
  577.             End;
  578.  
  579.     (* acquire/generate image data for all image planes *)
  580.         If ImagePlane < planes Then
  581.             Begin
  582.       {tell the host what image plane is being returned; RGB images are one colour per plane}
  583.             loPlane := ImagePlane;
  584.             hiPlane := ImagePlane;
  585.  
  586.       (* make sure that the rows in the strip is not larger than the remaining image *)
  587.             If RowsInStrip > (imageSize.v - ImageRow + 1) Then
  588.                 Begin
  589.                 RowsInStrip := imageSize.v - ImageRow + 1;
  590.                 End;
  591.  
  592.       (* allocate memory for the image strip *)
  593.             data := NewPtrClear(RowsInStrip * rowBytes);
  594.  
  595.       (* check if the memory was allocated properly *)
  596.             If data = Nil Then
  597.                 Begin
  598.                 Result := memFullErr;
  599.                 Exit(DoContinue)
  600.                 End;
  601.  
  602.       (* position and size of the image strip; Photoshop starts at zero thus the "-1" *)
  603.             SetRect(theRect, 0, ImageRow - 1, imageSize.h, ImageRow + RowsInStrip - 1);
  604.  
  605.       (* have our pointer point to the start of the image strip memory *)
  606.             TheStripPtr := data;
  607.  
  608.       (* loop through all of the rows in the image strip *)
  609.             For aRow := ImageRow To ImageRow + RowsInStrip - 1 Do
  610.                 Begin
  611.  
  612.         (* check if the user has pressed command-period; exit if true *)
  613.                 If TestAbort(myData) Then
  614.                     Begin
  615.                     Result := kAbortAcquisition;
  616.                     Exit(DoContinue)
  617.                     End;
  618.  
  619.         {tell the host to update its progress bar}
  620.                 UpdateProgress(ImagePlane * ORD4(imageSize.v) + aRow, planes * ORD4(imageSize.v), myData);
  621.  
  622.         (* This is where values are assigned to the pixels in the image. *)
  623.         (* One would normally read in an image from disc or a scanner or just*)
  624.     (* generate a pretty picture using fractals or what-ever. *)
  625.         (* Here we just generate a pretty picture. *)
  626.         {$PUSH}
  627.         {$R-}
  628.                 Case ImageMode Of
  629.         {for a bitmapped image, set the values of 8 pixels at once}
  630.                 acquireModeBitmap: 
  631.                     Begin
  632.           (* loop through all bytes in one row of the image strip *)
  633.                     For aColumn := 0 To rowBytes - 1 Do
  634.                         Begin
  635.                         TheStripPtr^ := BSL($FF, BAND(aRow, 7));
  636.             (* point to the next byte in the image strip *)
  637.                         TheStripPtr := Ptr(ORD4(TheStripPtr) + 1);
  638.                         End;  {For aColumn}
  639.                     End;  {acquireModeBitmap}
  640.  
  641.         {place one byte in each pixel; only have one image plane to worry about}
  642.                 acquireModeGrayScale: 
  643.                     Begin
  644.           (* loop through all bytes/pixels in one row of the image strip *)
  645.                     For aColumn := 0 To rowBytes - 1 Do
  646.                         Begin
  647.                         TheStripPtr^ := BAND(aColumn + aRow, $FF);
  648.             (* point to the next byte in the image strip *)
  649.                         TheStripPtr := Ptr(ORD4(TheStripPtr) + 1);
  650.                         End;  {For aColumn}
  651.                     End;  {acquireModeGrayScale}
  652.  
  653.         {place one byte in each pixel; only have one image plane to worry about}
  654.                 acquireModeIndexedColor: 
  655.                     Begin
  656.           (* loop through all bytes/pixels in one row of the image strip *)
  657.                     For aColumn := 0 To rowBytes - 1 Do
  658.                         Begin
  659.                         TheStripPtr^ := BAND(aRow + aColumn, $FF);
  660.             (* point to the next byte in the image strip *)
  661.                         TheStripPtr := Ptr(ORD4(TheStripPtr) + 1);
  662.                         End;  {For aColumn}
  663.                     End;  {acquireModeIndexedColor}
  664.  
  665.         {for an RGB image, place different values in each of the 3 image planes}
  666.                 acquireModeRGBColor: 
  667.                     Begin
  668.           (* loop through all bytes/pixels in one row of the image strip *)
  669.                     For aColumn := 0 To rowBytes - 1 Do
  670.                         Begin
  671.                         Case ImagePlane Of
  672.                         0: 
  673.                             TheStripPtr^ := BAND(aColumn, $FF);
  674.                         1: 
  675.                             TheStripPtr^ := BAND(aRow - 1, $FF);
  676.                         2: 
  677.                             TheStripPtr^ := BAND(aRow - 1 + aColumn, $FF);
  678.  
  679.                         Otherwise
  680.                             Begin
  681.                             End;
  682.                         End;  {Case ImagePlane}
  683.  
  684.             (* point to the next byte in the image strip *)
  685.                         TheStripPtr := Ptr(ORD4(TheStripPtr) + 1);
  686.                         End;  {For aColumn}
  687.                     End;  {acquireModeRGBColor}
  688.  
  689.                 Otherwise
  690.                     Begin
  691.                     Result := kAbortAcquisition;
  692.                     End;
  693.                 End;  {Case ImageMode}
  694.  
  695.         {$POP}
  696.                 End;  {For aRow}
  697.  
  698.       {move to the start of the next image strip}
  699.             ImageRow := ImageRow + RowsInStrip;
  700.  
  701.       {if we have reached the end of an image plane then move onto the next image plane}
  702.             If ImageRow > imageSize.v Then
  703.                 Begin
  704.                 ImageRow := 1;
  705.                 ImagePlane := ImagePlane + 1
  706.                 End;
  707.  
  708.             End;  {If ImagePlane}
  709.         End;  {With}
  710.     End;  {DoContinue}
  711.  
  712.  
  713. (**** This routine will always be called if DoStart does not return an error ****)
  714. (**** even if DoContinue returns an error or the user aborts the operation ****)
  715. (****  This allows the Plug-In to delete the image strip buffer ****)
  716.     Procedure DoFinish (Var myData: myDataHand);
  717.     Begin
  718.   {if the image strip data buffer is not empty, then delete it}
  719.     If myData <> Nil Then
  720.         Begin
  721.         With myData^^.Acquire^ Do
  722.             If data <> Nil Then
  723.                 Begin
  724.                 DisposPtr(data);
  725.                 data := Nil
  726.                 End;
  727.         End;
  728.     End;  {DoFinish}
  729.  
  730.  
  731.   (**** Main dispatching routine.  Initialises and sets up the record variables,****)
  732.   (**** and performs the operation specified by the host's selector. ****)
  733.   (**** Think pascal wants this to be called "Main" to be placed first in the resource. ****)
  734.   (**** other development systems may require that this be the first routine in the source code ****)
  735.     Procedure Main (selector: Integer; AcquireRecord: AcquireRecordPtr; Var myData: Handle; Var result: Integer);
  736.  
  737.     Begin
  738.     result := NoErr;
  739.  
  740.   { See if this is the first time called }
  741.   {If so, allocate and initialise the record handle for our variables}
  742.     If (myData = Nil) Then
  743.         Begin
  744.     {allocate memory for our record}
  745.         myData := NewHandleClear(SizeOf(myDataType));
  746.  
  747.     {check if the memory allocation was successful}
  748.         If myData = Nil Then
  749.             Begin
  750.             result := MemFullErr;
  751.             Exit(Main);
  752.             End;
  753.  
  754.     { Initialize our plug-in values }
  755.         myDataHand(myData)^^.LastRows := 256;
  756.         myDataHand(myData)^^.LastCols := 256;
  757.         myDataHand(myData)^^.LastMode := acquireModeRGBColor
  758.         End;
  759.  
  760.   {lock the handle just to be certain}
  761.     HLock(myData);
  762.  
  763.   {keep track of the pointer to the AcquireRecord}
  764.     myDataHand(myData)^^.Acquire := AcquireRecord;
  765.  
  766.   {no error - yet}
  767.     myDataHand(myData)^^.Result := noErr;
  768.  
  769.   {perform the requested action}
  770.     Case selector Of
  771.  
  772.     acquireSelectorAbout: {show the about dialogue}
  773.         DoAbout;
  774.  
  775.     acquireSelectorPrepare: {set things up for acquisition}
  776.         DoPrepare(myDataHand(myData));
  777.  
  778.     acquireSelectorStart: {get parameters from the user}
  779.         DoStart(myDataHand(myData));
  780.  
  781.     acquireSelectorContinue: {acquire or produce the image}
  782.         DoContinue(myDataHand(myData));
  783.  
  784.     acquireSelectorFinish: {tidy things up before modual is disposed of}
  785.         DoFinish(myDataHand(myData));
  786.  
  787.     Otherwise
  788.         myDataHand(myData)^^.Result := acquireBadParameters
  789.  
  790.     End;  {Case selector}
  791.  
  792.   {return the result of the request}
  793.     result := myDataHand(myData)^^.Result;
  794.  
  795.   {unlock the handle before returning to the host programme}
  796.     HunLock(myData);
  797.     End;  {Main}
  798.  
  799. End.